home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
dev
/
lang
/
PPCSmllEiffel.lha
/
PPCSmallEiffel
/
lib_se
/
jvm.e
< prev
next >
Wrap
Text File
|
1998-01-16
|
20KB
|
885 lines
-- This file is part of SmallEiffel The GNU Eiffel Compiler.
-- Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
-- Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
-- http://www.loria.fr/SmallEiffel
-- SmallEiffel is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 2, or (at your option) any later
-- version. SmallEiffel is distributed in the hope that it will be useful,but
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for more details. You should have received a copy of the GNU General
-- Public License along with SmallEiffel; see the file COPYING. If not,
-- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
class JVM
--
-- Handling of Java Virtual Machine byte code generation.
--
inherit CODE_PRINTER;
creation make
feature
output_name: STRING;
-- This name is used as the name of the main output class
-- file and as the name of the directory used to store
-- auxilliary class files.
feature {NONE}
b_put_u1_count: INTEGER;
-- To count printed bytes.
feature {NONE}
make is do end;
feature {NONE}
fields: FIXED_ARRAY[RUN_FEATURE] is
once
!!Result.with_capacity(4);
end;
methods: FIXED_ARRAY[RUN_FEATURE] is
once
!!Result.with_capacity(64);
end;
feature {RUN_FEATURE}
add_field(rf: RUN_FEATURE) is
require
rf /= Void;
not fields.fast_has(rf)
do
fields.add_last(rf);
ensure
fields.fast_has(rf)
end;
feature {RUN_FEATURE,NATIVE}
add_method(rf: RUN_FEATURE) is
require
rf /= Void;
not methods.fast_has(rf)
do
methods.add_last(rf);
ensure
methods.fast_has(rf)
end;
feature
set_output_name(n: STRING) is
do
output_name := n;
end;
feature {SMALL_EIFFEL}
mkdir(root: RUN_FEATURE) is
-- Create a new directory to store class files.
require
root /= Void;
small_eiffel.is_ready
do
if output_name = Void then
output_name := root.current_type.base_class_name.to_string;
output_name := output_name.twin;
output_name.to_lower;
end;
if output_name.has_suffix(class_suffix) then
output_name.remove_suffix(class_suffix);
end;
echo.put_string("Trying to prepare directory %"");
echo.put_string(output_name);
echo.put_string("%" to store Java byte code.%N");
file_tools.mkdir(output_name);
end;
write_jvm_root_class is
local
idx: INTEGER;
cp: like constant_pool;
do
cp := constant_pool;
start_directory(out_file_path,output_name);
out_file_path.append(fz_jvm_root);
out_file_path.append(class_suffix);
bfw_connect(out_file,out_file_path);
start_basic;
access_flags := 1025; -- (ACC_PUBLIC,ACC_ABSTRACT)
this_class_idx := cp.idx_class2(jvm_root_class);
super_class_idx := cp.idx_java_lang_object;
-- Fields :
args_field;
manifest_string_pool.jvm_define_fields;
once_routine_pool.jvm_define_fields;
if run_control.no_check then
field_info.add(9,cp.idx_uft8(fz_58),cp.idx_uft8(fz_41));
end;
-- Methods :
-- The initialize method :
current_frame := Void;
method_info.start(9,fz_28,fz_29);
manifest_string_pool.jvm_initialize_fields;
once_routine_pool.jvm_initialize_fields;
if run_control.no_check then
idx := cp.idx_fieldref3(jvm_root_class,fz_58,fz_41);
code_attribute.opcode_iconst_0;
code_attribute.opcode_putstatic(idx,-1);
end;
code_attribute.opcode_return;
method_info.finish;
-- For switches :
switch_collection.jvm_define;
finish_class;
end;
write_main_class(rf3: RUN_FEATURE_3) is
-- Write Java Byte Code for main class to call `rf3'.
require
rf3 /= Void;
small_eiffel.is_ready
local
idx: INTEGER;
cp: like constant_pool;
ca: like code_attribute;
do
cp := constant_pool;
ca := code_attribute;
out_file_path.copy(output_name);
out_file_path.append(class_suffix);
bfw_connect(out_file,out_file_path);
start_basic;
access_flags := 16; -- (ACC_FINAL)
this_class_idx := cp.idx_class2(output_name);
super_class_idx := cp.idx_java_lang_object;
-- Methods :
-- The main method :
current_frame := Void;
method_info.start(9,fz_main,fz_23);
set_args_field;
idx := cp.idx_methodref3(jvm_root_class,fz_28,fz_29);
ca.opcode_invokestatic(idx,0);
rf3.run_class.jvm_push_default;
idx := cp.idx_methodref(rf3);
ca.opcode_invokevirtual(idx,-1);
ca.opcode_system_out;
idx := cp.idx_methodref3(fz_25,fz_42,fz_29);
ca.opcode_invokevirtual(idx,-1);
ca.opcode_system_err;
ca.opcode_invokevirtual(idx,-1);
ca.opcode_return;
method_info.finish;
finish_class;
end;
feature {CODE_ATTRIBUTE}
max_locals: INTEGER is
do
if current_frame /= Void then
Result := current_frame.jvm_max_locals;
else
Result := 4;
end;
end;
feature {NONE}
access_flags: INTEGER;
-- of the class.
this_class_idx: INTEGER;
super_class_idx: INTEGER;
start_basic is
do
fields.clear;
methods.clear;
constant_pool.clear;
field_info.clear;
method_info.clear;
b_put_u1_count := 0;
end;
feature {RUN_CLASS}
start_new_class(rc: RUN_CLASS) is
require
output_name /= Void
local
name_idx, type_idx: INTEGER;
cp: like constant_pool;
do
cp := constant_pool;
start_basic;
tmp_string.copy(rc.unqualified_name);
tmp_string.to_lower;
start_directory(out_file_path,output_name);
out_file_path.append(tmp_string);
out_file_path.append(class_suffix);
bfw_connect(out_file,out_file_path);
access_flags := 16;
this_class_idx := rc.fully_qualified_constant_pool_index;
super_class_idx := cp.idx_jvm_root_class;
-- <clinit> :
method_info.start(9,fz_76,fz_29);
-- generating_type :
name_idx := cp.idx_uft8(us_generating_type);
type_idx := cp.idx_eiffel_string_descriptor;
field_info.add(9,name_idx,type_idx);
name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
code_attribute.opcode_aconst_null;
code_attribute.opcode_putstatic(name_idx,-1);
-- generator :
name_idx := cp.idx_uft8(us_generator);
field_info.add(9,name_idx,type_idx);
name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
code_attribute.opcode_aconst_null;
code_attribute.opcode_putstatic(name_idx,-1);
code_attribute.opcode_return;
method_info.finish;
rc.jvm_define_class_invariant;
end;
finish_class is
-- Really print the class file.
do
put_magic;
put_minor_version;
put_major_version;
constant_pool.write_bytes;
b_put_u2(access_flags);
b_put_u2(this_class_idx);
b_put_u2(super_class_idx);
-- interfaces_count :
b_put_u2(0);
field_info.write_bytes;
method_info.write_bytes;
-- attributes_count :
b_put_u2(0);
out_file.disconnect;
echo.print_count("byte",b_put_u1_count);
end;
feature
current_frame: RUN_FEATURE;
-- Current method or current field.
feature {RUN_CLASS,SWITCH_COLLECTION}
set_current_frame(cf: like current_frame) is
do
current_frame := cf;
end;
feature
argument_offset_of(an: ARGUMENT_NAME): INTEGER is
require
an /= Void
do
Result := current_frame.jvm_argument_offset(an);
ensure
Result >= 0
end;
local_offset_of(ln: LOCAL_NAME): INTEGER is
require
ln /= Void
do
Result := current_frame.jvm_local_variable_offset(ln);
ensure
Result >= 0
end;
result_offset: INTEGER is
do
Result := current_frame.jvm_result_offset;
end;
feature {CP_INFO}
b_put_u1(byte: CHARACTER) is
require
0 <= byte.code;
byte.code <= 255
do
out_file.put_byte(byte);
b_put_u1_count := b_put_u1_count + 1;
end;
feature {CONSTANT_POOL,FIELD_INFO,METHOD_INFO}
b_put_u2(u2: INTEGER) is
do
b_put_u1((u2 // 256).to_character);
b_put_u1((u2 \\ 256).to_character);
ensure
b_